package com.yantong.service.xcx.impl;

import com.alibaba.fastjson.JSONObject;
import com.yantong.mapper.XLoginInfoMapper;
import com.yantong.utils.HttpUtil;
import com.yantong.pojo.Centre;
import com.yantong.pojo.Member;
import com.yantong.pojo.UserRegistrationDTO;
import com.yantong.pojo.XLoginInfo;
import com.yantong.pojo.bo.UserInfoBo;
import com.yantong.result.ResultVo;
import com.yantong.service.CentreService;
import com.yantong.service.MemberService;
import com.yantong.service.UserRegistrationService;
import com.yantong.service.xcx.XCXLoginService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author: juzi
 * @date: 2021/12/2
 * @time: 9:34
 */
@Service
@Slf4j
public class XCXLoginServiceImpl implements XCXLoginService {

    @Autowired
    private CentreService centreService;
    @Autowired
    private XLoginInfoMapper xLoginInfoMapper;
    @Autowired
    private MemberService memberService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private UserRegistrationService userRegistrationService;

    @Override
    public ResultVo getTokenByCentreIdAndCode(Long centreId, Long memberId, String code) {
        Centre centre = centreService.getByKey(centreId);
        if(null==centre){
            return ResultVo.error("商户不存在");
        }

        String appid = centre.getRelateAccount();
        String secret = centre.getAccountTel();

        if(StringUtils.isEmpty(appid) || StringUtils.isEmpty(secret)){
            return ResultVo.error("商户小程序未配置");
        }

        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appid
                + "&secret="+ secret
                + "&js_code="+ code
                + "&grant_type=authorization_code";
        JSONObject jsonObject = HttpUtil.sendGet(url);

        //如果微信返回状态码不为0 , 则判断登陆失败
        if(jsonObject.getIntValue("errcode")!=0){
            log.info("小程序登陆失败 , errcode = {} , errmsg = {}",
                    jsonObject.getIntValue("errcode"),
                    jsonObject.getString("errmsg"));

            return ResultVo.error(jsonObject.getString("errmsg"));
        }

        //根据openid/centreId/memberId查询用户是否已登陆过
        String openId = jsonObject.getString("openid");
        if(StringUtils.isEmpty(openId)){
            return ResultVo.error("openId未成功获取");
        }
        XLoginInfo xLoginInfo = new XLoginInfo();
        xLoginInfo.setCentreId(centreId);
        xLoginInfo.setMemberId(memberId);
        xLoginInfo.setOpenId(openId);

        XLoginInfo userInfo = xLoginInfoMapper.selectOne(xLoginInfo);
        ResultVo resultVo = new ResultVo();
        resultVo.put("openId",openId);
        resultVo.put("sessionKey",jsonObject.getString("session_key"));

        //如果未查询到 , 则进入注册逻辑
        if(userInfo == null){
            resultVo.put("code",-1);
            resultVo.put("msg","账号未注册");
            return resultVo;
        }

        //如果未查询到用户
        Member member = memberService.getByKey(userInfo.getMyMemberId());
        if(null == member){
            resultVo.put("code",-1);
            resultVo.put("msg","账号未注册");
            return resultVo;
        }

        resultVo = createToken(member);
        resultVo.put("openId",openId);
        resultVo.put("sessionKey",jsonObject.getString("session_key"));
        return resultVo;
    }

    @Override
    public ResultVo register(UserInfoBo userInfoBo) {
        //查询用户是否已存在(可能在本地生活/其他小程序登陆过)
        Member member = memberService.getOneByCentreIdAndMobile(userInfoBo.getCentreId(),userInfoBo.getMobile());

        //查询登录信息表是否已存在 --- 用以防止前端多次调用注册接口
        XLoginInfo xLoginInfo = new XLoginInfo();
        xLoginInfo.setCentreId(userInfoBo.getCentreId());
        xLoginInfo.setMemberId(userInfoBo.getMemberId());
        xLoginInfo.setOpenId(userInfoBo.getOpenId());
        xLoginInfo.setMobile(userInfoBo.getMobile());
        XLoginInfo userInfo = xLoginInfoMapper.selectOne(xLoginInfo);
        if(null != userInfo){
            xLoginInfo = userInfo;
        }

        //如果不存在则进入注册逻辑
        if(null == member){
            String ticket = String.valueOf(new Random().nextInt(999999));
            member = new Member();
            member.setAppOpenid(userInfoBo.getOpenId());
            member.setAvatar(userInfoBo.getAvatarUrl());
            member.setNickname(userInfoBo.getNickName());
            member.setGender(Integer.valueOf(userInfoBo.getGender()));
            member.setLoginMobile(userInfoBo.getMobile());
            member.setMobile(userInfoBo.getMobile());
//        member.setProvince(userInfoBo.getProvince());
//        member.setCity(userInfoBo.getCity());
            member.setTicket(ticket);
            //门店信息
            Member mem = memberService.getTmByKey(userInfoBo.getMemberId());
            member.setCentreId(mem.getCentreId());
            member.setTeamid(mem.getId());
            member.setUpshopName(StringUtils.isEmpty(mem.getRealname()) ? mem.getNickname() : mem.getRealname());
            member.setUpshopTid(mem.getId());

            //推荐用户不为空
            Long mid = userInfoBo.getMid();
            if (mid != null) {
                log.info("==mid!=nul===" + (mid != null));
                //查找推荐用户
                mem = memberService.getTmByKey(mid);
                if (mem != null) {
                    log.info("==mem!=nul===" + mem.getId());
                    //设置推荐人
                    member.setUserid(mem.getId());
                    log.info("==mem===" + JSONObject.toJSONString(mem));
                    member.setUserName(StringUtils.isEmpty(mem.getRealname()) ? mem.getNickname() :
                            mem.getRealname());
                    //用户推荐人的推荐人不为空
                    if (mem.getUserid() != null) {
                        //设置上级推荐人
                        member.setUpUserid(mem.getUserid());
                        member.setUpuserName(mem.getUserName());
                    }
                }

            }
            if (member.getCentreId() == null) {
                member.setCentreId(userInfoBo.getCentreId());
            }

            log.info("==member===" + JSONObject.toJSONString(member));
            long id = memberService.saveMember(member);
            log.info("小程序新增用户成功");
            if (id < 0) {
                return ResultVo.error();
            }
            redisTemplate.opsForValue().set("isNew:" + id, "true", 7, TimeUnit.DAYS);

            Member memberParam = memberService.getByKey(member.getId());
            //新注册用户特殊业务分支处理（商户的特殊需求）
            UserRegistrationDTO userRegistrationDTO = new UserRegistrationDTO();
            userRegistrationDTO.setMember(memberParam);
            userRegistrationService.userRegistrationBusinessProcess(userRegistrationDTO);
            xLoginInfo.setMyMemberId(id);
        }else {
            //建议与小程序的对应关系
            xLoginInfo.setMyMemberId(member.getId());
        }

        if(null != xLoginInfo.getId()){
            xLoginInfoMapper.update(xLoginInfo);
        }else {
            xLoginInfo.setCreateTime(new Date());
            xLoginInfoMapper.insert(xLoginInfo);
        }


        return createToken(member);
    }


    private ResultVo createToken(Member member) {
        ResultVo resultVo = new ResultVo();
        //不要返回到前端
        member.setTicket(null);

        String sign = DigestUtils.md5Hex(member.getId() + member.getOpenid());
        JSONObject autoToken = new JSONObject();
        autoToken.put("id", member.getId());
        autoToken.put("oid", member.getOpenid());
        autoToken.put("sign", sign);

        if (member.getGrade() == null) {
            member.setGrade(1);
        }
        resultVo.put("data", member);
        resultVo.put("success", true);
        String authTokenStr = Base64Utils.encodeToString(autoToken.toJSONString().getBytes(StandardCharsets.UTF_8));
        resultVo.put("authToken", authTokenStr);
        //使用LoginUser注解需要
        redisTemplate.opsForValue().set(authTokenStr, member.getId().toString());
        return resultVo;

    }


}
